package com.db.logger;

import com.db.logger.appender.Appender;
import com.db.logger.appender.AppenderFactory;
import com.db.logger.layout.Layout;
import com.db.logger.domain.LoggerLevel;
import com.db.logger.layout.LayoutFactory;
import com.db.logger.service.ConfigService;

import java.util.HashMap;
import java.util.Map;

public class LoggerFactory {
    private static Map<String, Logger> loggerMap = new HashMap<>();

    public synchronized static Logger getLogger(String loggerName) {
        if (loggerMap.containsKey(loggerName)) {
            return loggerMap.get(loggerName);
        } else {
            LoggerLevel loggerLevel = getLoggerLevel(loggerName);
            Appender appender = AppenderFactory.getAppender(getAppenderName(loggerName), loggerName);
            Layout layout = LayoutFactory.getLayout(getLayoutName(loggerName), loggerName);

            Logger logger = new LoggerImpl(loggerLevel, appender, layout);
            loggerMap.put(loggerName, logger);
            return logger;
        }
    }

    private static LoggerLevel getLoggerLevel(String loggerName) {
        String loggerLevelName = ConfigService.getProperty(loggerName, "level");
        if (loggerLevelName == null) {
            throw new RuntimeException("Can not get logger level name for " + loggerName);
        }
        try {
            return LoggerLevel.valueOf(loggerLevelName);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Can not init logger level for " + loggerName);
        }
    }

    private static String getAppenderName(String loggerName) {
        String appenderName = ConfigService.getProperty(loggerName, "appender");
        if (appenderName != null) {
            return appenderName;
        } else {
            throw new RuntimeException("Can not get appender name for " + loggerName);
        }
    }

    private static String getLayoutName(String loggerName) {
        String layoutName = ConfigService.getProperty(loggerName, "layout");
        if (layoutName != null) {
            return layoutName;
        } else {
            throw new RuntimeException("Can not get layout name for " + loggerName);
        }
    }
}
